home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / master / Examples / Visual / VMake / symbol.c < prev    next >
C/C++ Source or Header  |  1994-02-01  |  8KB  |  269 lines

  1. #ifdef MAIN
  2. #include <stdio.h>
  3. #include <string.h>
  4. #define free_mem(a,b) free(a)
  5. #define get_mem(a)    malloc(a)
  6. #define Prototype
  7. #else
  8. #include "vmake.h"
  9. #endif
  10. struct SYMBOL {
  11.   struct SYMBOL *next;
  12.   char *val;
  13.   short curlen;
  14.   short allotlen;
  15.   char name[1];
  16. };
  17. Prototype void Sym_Clear(void);
  18. Prototype void *Sym_Next(void *cursym, char **name, char **val);
  19. Prototype char *Sym_Lookup(char *name);
  20. Prototype int Sym_Set(char *name, char *val1, char *val2);
  21.  
  22. struct SYMBOL *base, *last; /* Root and end of all symbol entries   */
  23. struct SYMBOL *symcache;    /* Cached entry of last symbol found    */
  24. /***********************************************************************************
  25.  * Procedure: Sym_Clear
  26.  * Synopsis:  rc = set_option(object, optstr)
  27.  * Purpose:   Clear out all of the symbols.  This leaves private ones untouched
  28.  ***********************************************************************************/
  29. void Sym_Clear()
  30. {
  31.    struct SYMBOL *sym, *symnext, *savesym;
  32.  
  33.    savesym = NULL;
  34.  
  35.    sym = base;
  36.    base = last = NULL;
  37.  
  38.    while(sym != NULL)
  39.    {
  40.       symnext = sym->next;
  41.       if (sym->name[0] == '_')
  42.       {
  43.          if (base == NULL)
  44.          {
  45.             base = last = sym;
  46.          }
  47.          else
  48.          {
  49.             last = last->next = sym;
  50.          }
  51.          sym->next = NULL;
  52.       }
  53.       else
  54.       {
  55.          free_mem(sym->val, sym->allotlen);
  56.          free_mem(sym, sizeof(struct SYMBOL) + strlen(sym->name));
  57.       }
  58.       sym = symnext;
  59.    }
  60.    symcache = NULL;
  61. }
  62.  
  63. /***********************************************************************************
  64.  * Procedure: Sym_Next
  65.  * Synopsis:  place = Sym_Next(place, &name, &val);
  66.  * Purpose:   Return the next public symbol in a string
  67.  ***********************************************************************************/
  68. void *Sym_Next(void *cursym,
  69.                char **name,
  70.                char **val)
  71. {
  72.    struct SYMBOL *sym;
  73.    sym = (struct SYMBOL *)cursym;
  74.  
  75.    if (sym == NULL) sym = base;
  76.    else sym = sym->next;
  77.  
  78.    while (sym && (sym->name[0] == '_'))
  79.    {
  80.       sym = sym->next;
  81.    }
  82.  
  83.    *name = "ILLEGAL";
  84.    *val  = "ILLEGAL";
  85.    if (sym != NULL)
  86.    {
  87.       *name = sym->name;
  88.       *val  = sym->val;
  89.    }
  90.    return(sym);
  91. }
  92.  
  93. /***********************************************************************************
  94.  * Procedure: findsymbol
  95.  * Synopsis:  SYMBOL = findsymbol(name);
  96.  * Purpose:   Find the symbol entry for a given name
  97.  ***********************************************************************************/
  98. static struct SYMBOL *findsymbol(char *name)
  99. {
  100.    struct SYMBOL *sym;
  101.    /* See if they are asking for the one we hit last time */
  102.    if (symcache && !strcmp(symcache->name, name)) return(symcache);
  103.    /* Not the same one, do a sequential search on the list.  We can do this     */
  104.    /* Because we know that the number of entries that are generally stored      */
  105.    /* is quite small.  If we change this, this routine would have to be updated */
  106.    for(sym = base; sym != NULL; sym = sym->next)
  107.    {
  108.       if (!strcmp(sym->name, name))
  109.       {
  110.          symcache = sym;      /* Remember it for the cache */
  111.          break;
  112.       }
  113.    }
  114.    return(sym);
  115. }
  116.  
  117. /***********************************************************************************
  118.  * Procedure: Sym_Lookup
  119.  * Synopsis:  val = Sym_Lookup(name)
  120.  * Purpose:   Find the substitution value for a string
  121.  *            If the symbol is not found, a null string is returned.
  122.  *            Originally this returned NULL, but everyone that wants to use it was
  123.  *            checking for this case and then setting the string to "" anyway.
  124.  *            We can create a new routine if this were desired.
  125.  ***********************************************************************************/
  126. char *Sym_Lookup(char *name)
  127. {
  128.    struct SYMBOL *sym;
  129.  
  130.    sym = findsymbol(name);
  131.    if (sym) return(sym->val);
  132.    return("");
  133. }
  134.  
  135. /***********************************************************************************
  136.  * Procedure: Sym_Set
  137.  * Synopsis:  rc = Sym_Set(name, val1, val2)
  138.  * Purpose:   Set a symbol to the concatenation of two values
  139.  ***********************************************************************************/
  140. int Sym_Set(char *name, char *val1, char *val2)
  141. {
  142.    struct SYMBOL *sym;
  143.    int len2, len, len1;
  144.    char *newval;
  145.  
  146.    sym = findsymbol(name);
  147.    if (sym == NULL)
  148.    {
  149.       /* There is a first time for everything, create an empty structure */
  150.       sym = get_mem(sizeof(struct SYMBOL)+strlen(name));
  151.       if (sym == NULL) return(1);
  152.       strcpy(sym->name, name);
  153.       sym->curlen = sym->allotlen = 0;
  154.       sym->val = "";
  155.       sym->next = NULL;
  156.       if (last)
  157.          last->next = sym;
  158.       else
  159.          base = sym;
  160.       last = sym;
  161.    }
  162.  
  163.    /* If they pass NULL as the first parameter, we are doing a concat */
  164.    if (val1 == NULL) val1 = sym->val;
  165.  
  166.    /* We have a valid symbol, see if we can tack on to the end of it */
  167.    /* This one special case will occur when we do concenation to the */
  168.    /* end of a string                                                */
  169.    if (val2 == NULL) val2 = "";
  170.    len2 = strlen(val2);
  171.    if ((val1 == sym->val) && ((sym->curlen + len2) < sym->allotlen))
  172.    {
  173.       /* It is just a tackon case  */
  174. #ifdef MAIN
  175.       printf("Tackon: %d to %d allot=%d\n", len2, sym->curlen, sym->allotlen);
  176. #endif
  177.       strcpy(sym->val+sym->curlen, val2);
  178.       sym->curlen += len2;
  179.       return(0);
  180.    }
  181.  
  182.    /* No, we need to allocate a new area and copy from the two strings into  */
  183.    /* That location.  Note that we can not free the original area because it */
  184.    /* is possible that one of the strings point to it.                       */
  185.    len1 = strlen(val1);
  186.    len = (len1 + len2 + 64) & ~63;
  187. #ifdef MAIN
  188.    printf("Allocate %d for %d + %d\n", len, len1, len2);
  189. #endif
  190.    newval = get_mem(len);
  191.    if (newval == NULL) return(1);
  192.    strcpy(newval, val1);
  193.    strcpy(newval+len1, val2);
  194.    if (sym->allotlen) free_mem(sym->val, sym->allotlen);
  195.    sym->val = newval;
  196.    sym->allotlen = len;
  197.    sym->curlen = len1+len2;
  198.    return(0);
  199. }
  200. /***********************************************************************************
  201.  * Procedure: set_option
  202.  * Synopsis:  rc = set_option(object, optstr)
  203.  * Purpose:   Set an option based on a option string
  204.  ***********************************************************************************/
  205. #ifdef MAIN
  206. void main()
  207. {
  208.    char buf[100];
  209.    char *p;
  210.    void *place;
  211.    char *name, *val;
  212.    int rc;
  213.  
  214.    while((printf(">"), fflush(stdout), gets(buf)) != NULL)
  215.    {
  216.       name = buf+1;
  217.       switch(buf[0])
  218.       {
  219.          case 'd':
  220.             place = NULL;
  221.             while(place = Sym_Next(place, &name, &val))
  222.                printf("%s= %s\n", name, val);
  223.             break;
  224.          case 'p':
  225.             val = Sym_Lookup(name);
  226.             if (val)
  227.                printf("%s= %s\n", name, val);
  228.             else
  229.                printf("%s not found\n", name);
  230.             break;
  231.          case 'c':
  232.             Sym_Clear();
  233.             printf("Cleared\n");
  234.             break;
  235.          case 'a':
  236.          case 's':
  237.             p = name+1;
  238.             while(*p && *p != ' ') p++;
  239.             *p = 0;
  240.             val = p+1;
  241.             if (buf[0] == 'a')
  242.             {
  243.                p = Sym_Lookup(name);
  244.                printf("Setting '%s' to '%s%s'\n", name, p, val);
  245.                rc = Sym_Set(name, NULL, val);
  246.             }
  247.             else
  248.             {
  249.                printf("Setting '%s' to '%s'\n", name, val);
  250.                rc = Sym_Set(name, val, NULL);
  251.             }
  252.             if (rc) printf("Sym_Set failed\n");
  253.             break;
  254.          case 'q':
  255.             Sym_Clear();
  256.             return;
  257.          default:
  258.             printf("Unknown command: %s\n", buf);
  259.             printf("d         - Dump all symbols\n");
  260.             printf("p sym     - Print value of sym\n");
  261.             printf("c         - Clear all symbold\n");
  262.             printf("a sym val - Append val to sym\n");
  263.             printf("s sym val - Set sym to val\n");
  264.             break;
  265.       }
  266.    }
  267. }
  268. #endif
  269.